﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics.Contracts;

namespace Konst3d.Efficiency.IO
{
    public static class BinaryWriterExtender
    {
        public static void Write(this BinaryWriter writer, byte value, int offset, SeekOrigin origin = SeekOrigin.Begin)
        {
            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            writer.Write(value);
        }

        public static void Write(this BinaryWriter writer, int value, int offset, SeekOrigin origin = SeekOrigin.Begin)
        {
            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            writer.Write(value);
        }

        public static void Write(this BinaryWriter writer, uint value, int offset, SeekOrigin origin = SeekOrigin.Begin)
        {
            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            writer.Write(value);
        }

        public static void Write(this BinaryWriter writer, float value, int offset, SeekOrigin origin = SeekOrigin.Begin)
        {
            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            writer.Write(value);
        }

        public static void Write(this BinaryWriter writer, double value, int offset, SeekOrigin origin = SeekOrigin.Begin)
        {
            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            writer.Write(value);
        }

        public static void Write(this BinaryWriter writer, DateTime value, int offset = -1, SeekOrigin origin = SeekOrigin.Begin)
        {
            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            writer.Write(value.Year);
            writer.Write((byte)value.Month);
            writer.Write((byte)value.Day);
            writer.Write((byte)value.Hour);
            writer.Write((byte)value.Minute);
            writer.Write((byte)value.Second);

            writer.Flush();
        }

        public static void Write(this BinaryWriter writer, ShortDate date, int offset = -1, SeekOrigin origin = SeekOrigin.Begin)
        {
            writer.Write(date.Year, offset, origin);
            writer.Write(date.Month);
            writer.Write(date.Day);

            writer.Flush();
        }

        public static void WriteShortDate(this BinaryWriter writer, DateTime date, int offset = -1, SeekOrigin origin = SeekOrigin.Begin)
        {
            writer.Write(date.Year, offset, origin);
            writer.Write((byte)date.Month);
            writer.Write((byte)date.Day);

            writer.Flush();
        }

        public static void WriteBytes(this BinaryWriter writer, byte value, int count, int offset = -1, SeekOrigin origin = SeekOrigin.Begin)
        {
            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            var buff = new byte[count];

            for (int i = 0; i < buff.Length; ++i)
            {
                buff[i] = value;
            }

            writer.Write(buff);
            writer.Flush();
        }

        public static void WriteBytes(this BinaryWriter writer, byte[] value, int offset = -1, SeekOrigin origin = SeekOrigin.Begin)
        {
            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            if (value != null && value.Length > 0)
            {
                writer.Write(value);
                writer.Flush();
            }
        }

        public static void WriteString(this BinaryWriter writer, string value, Encoding encoding, int offset = -1, SeekOrigin origin = SeekOrigin.Begin)
        {
            Contract.Requires(encoding != null);

            byte[] data = null;

            if (!String.IsNullOrEmpty(value))
            {
                data = encoding.GetBytes(value);
            }
            else
            {
                data = new byte[0];
            }

            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            writer.Write(data.Length);
            writer.Write(data, 0, data.Length);

            writer.Flush();
        }

        public static void WriteString(this BinaryWriter writer, string value, ICryptographicEngine cryptographicEngine, int offset = -1, SeekOrigin origin = SeekOrigin.Begin)
        {
            Contract.Requires(cryptographicEngine != null);

            byte[] data = null;

            if (!String.IsNullOrEmpty(value))
            {
                data = cryptographicEngine.Encode(value);
            }
            else
            {
                data = new byte[0];
            }

            if (offset >= 0)
            {
                writer.Seek(offset, origin);
            }

            writer.Write(data.Length);
            writer.Write(data, 0, data.Length);

            writer.Flush();
        }
    }
}
